//------------------------------------------------------------------------------
// <copyright company="Telligent Systems">
//     Copyright (c) Telligent Systems Corporation.  All rights reserved.
// </copyright> 
//------------------------------------------------------------------------------

using System;
using System.Web.Caching;
using System.Xml;
using CommunityServer.Configuration;

namespace CommunityServer.Components
{
	/// <summary>
	/// Summary description for ApplicationConfiguration.
	/// </summary>
	[Serializable]
    public abstract class  ApplicationConfiguration
	{
		public ApplicationConfiguration()
		{
			
		}

        protected static ApplicationConfiguration Instance(Type type, bool useCache)
        {
            ApplicationConfiguration config = null;
            
            if(useCache)
            {
                config = CSCache.Get(CacheKey(type)) as ApplicationConfiguration;
            }

            if(config == null)
            {
                config = Activator.CreateInstance(type) as ApplicationConfiguration;
                if(config != null)
                {
                    XmlNode node = CSConfiguration.GetConfig().GetConfigSection(config.ConfigSection);
                    config.BaseSettings(node);
                    config.Initialize(node);

                    if(!config.FileOnly)
                    {
                        CommonDataProvider dp = CommonDataProvider.Instance();
                        object config2 = dp.GetApplicationConfigurationSettings(config.ApplicationType,type);
                        Merger.Merge(config,config2);
                    }

                    if(useCache)
                    {
                        CacheConfigSettings(config);
                    }

                }

                CSEvents.PostConfigurationInitialized(config);
            }

            return config;
        }

        private static string CacheKey(Type type)
        {
            return string.Format("AppConfig-{0}-{1}", type.FullName,CSContext.Current.SettingsID);
        }

        private static void CacheConfigSettings(ApplicationConfiguration appConfig)
        {
            appConfig._isCached = true;
            CacheDependency dep = new CacheDependency(null, new string[]{CSConfiguration.CacheKey});
			CSCache.Remove(CacheKey(appConfig.GetType()));
			CSCache.Insert(CacheKey(appConfig.GetType()), appConfig, dep,CSCache.MinuteFactor*15);
		}

		/// <summary>
		/// removes the specified application configuration from the cache if it exists;
		/// </summary>
		/// <param name="type"></param>
		protected static void Flush(Type type)
		{
			CSCache.Remove(CacheKey(type));
		}

        protected abstract string ConfigSection { get;}
        
        public abstract ApplicationType ApplicationType { get;}

        private bool _enabled = true;
        private bool _isLocked = false;
        private bool _allowNew = true;
        private bool _disabled = false;
        private bool _fileOnly = false;
        private bool _isCached = false;

        public bool Enabled
        {
            get{return _enabled;}
            set{_enabled = value;}
        }

        [ReadFromConfigurationFileOnly]
        public bool IsLocked
        {
            get{return _isLocked;}
        }

        [ReadFromConfigurationFileOnly]
        public bool IsCached
        {
            get{return _isCached;}
        }

        [ReadFromConfigurationFileOnly]
        public bool FileOnly
        {
            get{return _fileOnly;}
        }

        [ReadFromConfigurationFileOnly]
        public bool AllowNew
        {
            get{return _allowNew;}
        }

        [ReadFromConfigurationFileOnly]
        public bool Disabled
        {
            get{return _disabled;}
        }


        protected virtual void Initialize(XmlNode node)
        {
            
        }

        protected void BaseSettings(XmlNode node)
        {
            if(node != null)
            {
                XmlAttribute fo = node.Attributes["fileOnly"];
                if(fo != null)
                    this._fileOnly = bool.Parse(fo.Value);

                XmlAttribute att = node.Attributes["enable"];
                if(att != null)
                    this.Enabled = bool.Parse(att.Value);

                XmlAttribute loc = node.Attributes["locked"];
                if(loc != null)
                    this._isLocked = bool.Parse(loc.Value);

                XmlAttribute dis = node.Attributes["disabled"];
                if(dis != null)
                    this._disabled = bool.Parse(dis.Value);

                XmlAttribute allownew = node.Attributes["allowNew"];
                if(allownew != null)
                    this._allowNew = bool.Parse(allownew.Value);
            }
        }

        public virtual void Save()
        {
            if(!this.FileOnly)
            {
                CommonDataProvider dp = CommonDataProvider.Instance();
                dp.CreateUpdateApplicationConfigurationSettings(this.ApplicationType, this);

                //Update this copy to the cache if we are not already cached. This will not help
                //us in a cluster
                if(!this.IsCached)
                {
                    CacheConfigSettings(this);
                }
			}
        }
	}

    public abstract class ApplicationKeyApplicationConfiguration : ApplicationConfiguration
    {
        private string _defaultApplicationKey;

        [ReadFromConfigurationFileOnly]
        public string DefautApplicationKey
        {
            get{return _defaultApplicationKey;}
            set{_defaultApplicationKey = value;}
        }

        protected override void Initialize(XmlNode node)
        {
            base.Initialize(node);

            if(node != null)
            {
                XmlAttribute att = node.Attributes["defaultApplicationKey"];
                if(att != null)
                    this.DefautApplicationKey = att.Value;


            }
        }

    }

    public abstract class ThemedApplicationKeyApplicationConfiguration : ApplicationKeyApplicationConfiguration
    {

        protected bool _enableThemes = true;
        public bool EnableThemes
        {
            get { return _enableThemes; }
            set { _enableThemes = value; }
        }


		protected abstract string ThemeLocationDefault();

        protected string _themeLocation;
        public string ThemeLocation
        {
            get { return this._themeLocation; }
            set { _themeLocation = value; }
        }


        protected bool _enableSkinCache = true;
        public bool EnableSkinCache
        {
            get { return _enableSkinCache; }
        }


        protected string _defaultTemplate = "default";
        public string DefaultTheme
        {
            get { return _defaultTemplate; }
            set { _defaultTemplate = value; }
        }

        protected string _defaultSecondaryCSS = null;
        public string DefaultSecondaryCSS
        {
            get { return _defaultSecondaryCSS; }
            set { _defaultSecondaryCSS = value; }
        }

        protected string _baseTemplate = "default";
		
		[ReadFromConfigurationFileOnly]
		public string BaseTheme
        {
            get { return _baseTemplate; }
            set { _baseTemplate = value; }
        }

		protected override void Initialize(XmlNode node)
		{
			base.Initialize(node);

			_themeLocation = ThemeLocationDefault();

			if(node != null)
			{
				XmlAttribute et = node.Attributes["enableThemes"];
				if(et != null)
					this._enableThemes = bool.Parse(et.Value);

				XmlAttribute skinCache = node.Attributes["enableSkinCache"];
				if(skinCache != null)
					this._enableSkinCache = bool.Parse(skinCache.Value);

				XmlAttribute defaultTemplate = node.Attributes["defaultTheme"];
				if (defaultTemplate != null)
					this._defaultTemplate = defaultTemplate.Value;

				XmlAttribute defaultSecondaryCSS = node.Attributes["defaultSecondaryCSS"];
				if (defaultSecondaryCSS != null)
					this._defaultSecondaryCSS = defaultSecondaryCSS.Value;

				XmlAttribute baseTemplate = node.Attributes["baseTheme"];
				if (baseTemplate != null)
					this._baseTemplate = baseTemplate.Value;


				XmlAttribute themeLocation = node.Attributes["themeLocation"];
				if (themeLocation != null)
					this._themeLocation = themeLocation.Value;

			}
		}


    }
}
